<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>推流</title>
</head>

<body>
    <video id="webrtcVideo" autoplay></video>
    <script>
        const video = document.getElementById('webrtcVideo');
        // webscoket
        const roomId = 'webrtc';
        const id = Math.random();
        const url = `ws://118.25.18.233/websocket/ws/chat/${roomId}?id=${id}`;
        const ws = new WebSocket(url); // 可换成局域网ip地址
        let videoStream;
        // 一个拉流RTCPeerConnection对应一个推流RTCPeerConnection，xx个拉流RTCPeerConnection，对应xx个推流RTCPeerConnection
        const pushPool = {};
        // rtc connection
        let pushRtcCon;
        // 打开摄像头，video标签播放视频流
        const getStream = async () => {
            if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) console.log('不支持：getUserMedia');
            const stream = await navigator.mediaDevices.getUserMedia({video:true});
            video.srcObject = stream;
            videoStream = stream;
        }
        getStream();
        // 开始推流
        const startPush = (pullId) => {
            if (!pushPool[pullId]) pushPool[pullId] = pushRtcCon = new RTCPeerConnection();
            // rtc connection 添加track
            videoStream.getVideoTracks().forEach(track => {
                pushRtcCon.addTrack(track, videoStream);
            });
            // 监听icecandidate
            pushRtcCon.onicecandidate = (event) => {
                if (event.candidate) ws.send(JSON.stringify({ type: 'candidate', candidate: event.candidate, id: pullId }))
            }
            // 创建offer
            pushRtcCon.createOffer().then(offer => {
                console.log(offer)
                // 设置推流LocalDescription
                pushRtcCon.setLocalDescription(offer).then(() => { console.log('推流设置LocalDescription成功'); });
                // offer信息发送给拉流
                ws.send(JSON.stringify({ type: 'offer', id: pullId, offer }))
            });
        }
        // 开启websocket服务
        ws.addEventListener('open', () => {
            // 初始化推流通道
            ws.send(JSON.stringify({ type: 'push_init' }))
            console.log('websocket连接成功')
        });
        // 接收wenbscoket信息
        ws.addEventListener('message', (event) => {
            let data = JSON.parse(event.data);
            console.log(data)
            // 接收到拉流传来的answer 设置推流RemoteDescription
            if (data.type == 'answer') pushRtcCon.setRemoteDescription(data.answer).then(() => { console.log('推流设置RemoteDescription成功'); });
            // 接收拉流candidate 推流rtc connection 添加IceCandidate
            if (data.type == 'candidate' && data.candidate) pushRtcCon.addIceCandidate(data.candidate).then(() => { console.log('推流添加candidate成功'); });
            // 接收拉流开启消息 开始推流
            if (data.type == 'pull_start') startPush(data.id);
        })
    </script>
</body>

</html>